package com.yanqu.road.server.manager.activity.climbtower;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.climbtower.ClimbTowerDrawNoticeData;
import com.yanqu.road.entity.activity.climbtower.ClimbTowerTopData;
import com.yanqu.road.entity.activity.climbtower.ClimbTowerTopInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.bussiness.player.ClimbTowerActivityBussiness;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.ClimbTowerProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class CrossClimbTowerMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(CrossClimbTowerMgr.class.getName());
    static Map<Integer, List<ClimbTowerDrawNoticeData>> activityNoticeMap;
    static Map<Integer, CrossClimbTowerTop> activityTopMap = new ConcurrentHashMap<>();

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        activityTopMap.clear();

        Map<Integer, ActivityInfo> activityInfoMap = ActivityMgr.getOpenCrossActivityMapByType(eActivityType.ClimbTower.getValue());
        List<Integer> activityList = new ArrayList<>();
        for (Map.Entry<Integer, ActivityInfo> entry : activityInfoMap.entrySet()) {
            activityList.add(entry.getKey());
            activityTopMap.put(entry.getKey(), new CrossClimbTowerTop(entry.getKey(), entry.getValue().getEndShowTime()));
            CrossClimbTowerConfigMgr.reloadConfig(entry.getKey());
        }
        activityNoticeMap = ClimbTowerActivityBussiness.getClimbTowerDrawNoticeData(activityList);

        Map<Integer, Map<Integer, ClimbTowerTopData>> activityTopMapFromDb = ClimbTowerActivityBussiness.getClimbTowerTopData(activityList);

        if (null != activityTopMapFromDb) {
            for (Map.Entry<Integer, Map<Integer, ClimbTowerTopData>> entry : activityTopMapFromDb.entrySet()) {
                CrossClimbTowerTop crossClimbTowerTop = activityTopMap.get(entry.getKey());
                if (null == crossClimbTowerTop) {
                    continue;
                }
                for (Map.Entry<Integer, ClimbTowerTopData> topDataMap : entry.getValue().entrySet()) {
                    crossClimbTowerTop.initTopData(topDataMap.getValue());
                }
            }
        }

        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        for (Map.Entry<Integer, List<ClimbTowerDrawNoticeData>> listEntry : activityNoticeMap.entrySet()) {
            for (int i = 0; i < listEntry.getValue().size(); i++) {
                ClimbTowerDrawNoticeData data = listEntry.getValue().get(i);
                if (data.isInsertOption()) {
                    ClimbTowerActivityBussiness.addClimbTowerDrawNoticeData(data);
                } else if (data.isUpdateOption()) {
                    ClimbTowerActivityBussiness.updateClimbTowerDrawNoticeData(data);
                }
            }
        }

        try {
            long nowTimeSecond = DateHelper.getCurrentTime()/1000;
            List<Integer> endActivityList = new ArrayList<>();
            for (Map.Entry<Integer, CrossClimbTowerTop> mapTop : activityTopMap.entrySet()) {
                CrossClimbTowerTop crossClimbTowerTop = mapTop.getValue();
                if (null != crossClimbTowerTop) {
                    crossClimbTowerTop.save();
                    if (crossClimbTowerTop.getEndShowTime() + DateHelper.DAY_SECONDS < nowTimeSecond) {
                        endActivityList.add(mapTop.getKey());
                    }
                }
            }

            for (Integer activityId : endActivityList) {
                activityTopMap.remove(activityId);
                CrossClimbTowerConfigMgr.removeConfig(activityId);
            }
        } catch (Exception e) {
            logger.error("CrossClimbTowerMgr save err:", e);
        }

        return true;
    }

    public static void addDrawNotice(int activityId, long serverId, long playerId, List<ClimbTowerProto.ClimbTowerNoticeMsg> noticeList) {

        List<ClimbTowerDrawNoticeData> list = activityNoticeMap.get(activityId);
        if(list == null){
            synchronized (activityNoticeMap){
                list = activityNoticeMap.get(activityId);
                if(list == null){
                    list = new ArrayList<>();
                    activityNoticeMap.put(activityId, list);
                }
            }
        }

        synchronized (list){
            for (ClimbTowerProto.ClimbTowerNoticeMsg noticeMsg : noticeList) {
                ClimbTowerDrawNoticeData noticeData = new ClimbTowerDrawNoticeData();
                noticeData.setActivityId(activityId);
                noticeData.setGetTime(noticeMsg.getTime());
                noticeData.setServerId(serverId);
                noticeData.setUserId(playerId);
                noticeData.setNickName(noticeMsg.getNickName());
                noticeData.setReward(noticeMsg.getReward());
                noticeData.setParam(noticeMsg.getValue() + "");
                noticeData.setInsertOption();
                list.add(noticeData);
            }
            while (list.size() > 50){
                list.remove(0);
            }
        }
    }


    public static ClimbTowerProto.ClimbTowerNoticeRespMsg.Builder getNoticeList(int activityId) {
        ClimbTowerProto.ClimbTowerNoticeRespMsg.Builder respMsg = ClimbTowerProto.ClimbTowerNoticeRespMsg.newBuilder();

        List<ClimbTowerDrawNoticeData> list = activityNoticeMap.get(activityId);
        if(list != null){
            for (int i = 0; i < list.size(); i++) {
                ClimbTowerProto.ClimbTowerNoticeMsg.Builder builder = ClimbTowerProto.ClimbTowerNoticeMsg.newBuilder();
                ClimbTowerDrawNoticeData noticeData = list.get(i);
                builder.setTime(noticeData.getGetTime());
                builder.setReward(noticeData.getReward());
                builder.setServerId(noticeData.getServerId());
                builder.setNickName(noticeData.getNickName());
                builder.setValue(Integer.valueOf(noticeData.getParam()));
                respMsg.addNoticeList(builder);
            }
        }
        respMsg.setRet(0);
        return respMsg;
    }

    public static ClimbTowerProto.ClimbTowerTopCellListRespMsg.Builder getTopCellList(int activityId, long userId) {
        ClimbTowerProto.ClimbTowerTopCellListRespMsg.Builder respMsg = ClimbTowerProto.ClimbTowerTopCellListRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setNowTopCell(0);
        CrossClimbTowerTop crossClimbTowerTop = getCrossClimbTowerTop(activityId);
        if (null == crossClimbTowerTop) {
            return respMsg.setRet(GameErrorCode.E_CLIMB_TOWER_LOCK);
        }

        List<ClimbTowerTopInfo> topConfigList = CrossClimbTowerConfigMgr.getTopConfigList(activityId);
        if (null == topConfigList) {
            return respMsg.setRet(GameErrorCode.E_CLIMB_TOWER_TOP_CELL_CONFIG_NOTFOUND);
        }
        synchronized (crossClimbTowerTop) {
            for (ClimbTowerTopInfo topConfig : topConfigList) {
                ClimbTowerProto.ClimbTowerTopCellInfo.Builder topCellInfo = ClimbTowerProto.ClimbTowerTopCellInfo.newBuilder();
                topCellInfo.setCellNum(topConfig.getCellNum());
                topCellInfo.setReward(topConfig.getReward());
                ClimbTowerTopData topData = crossClimbTowerTop.getTopDataByCellNum(topConfig.getCellNum());
                if (null != topData && topData.getUserId() != 0) {
                    topCellInfo.setIsUser(true);
                    topCellInfo.setAbility(topData.getAbility().toString());
                    topCellInfo.setPic(topData.getPic());
                    topCellInfo.setLv(topData.getLv());
                    topCellInfo.setUserId(topData.getUserId());
                    CrossUserBaseInfo userBaseInfo = CrossUserMgr.getCrossUserBaseInfo(topData.getUserId());
                    if (null != userBaseInfo) {
                        topData.setUserBaseInfo(userBaseInfo.getUserBaseInfo());
                    }
                    topCellInfo.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(topData.getUserBaseInfo()));
                    if (topData.getUserId() == userId) {
                        respMsg.setNowTopCell(topConfig.getCellNum());
                    }
                } else {
                    topCellInfo.setIsUser(false);
                    topCellInfo.setAbility(topConfig.getAbility().toString());
                    topCellInfo.setPic(topConfig.getPic());
                }
                respMsg.addTopCellList(topCellInfo);
            }
        }
        return respMsg;
    }

    public static int topCellClimb(int activityId, long serverId, long userId, String ability, int pic, int lv, int maxCell, int targetCell, long targetUserId, UserBaseInfo userBaseInfo) {
        CrossClimbTowerTop crossClimbTowerTop = getCrossClimbTowerTop(activityId);
        if (null == crossClimbTowerTop) {
            return GameErrorCode.E_CLIMB_TOWER_LOCK;
        }

        ClimbTowerProto.ClimbTowerTopClimbRespMsg.Builder toSelfClientMsg = builderTopClimbRespMsg();
        ClimbTowerProto.CrossClimbTowerTopClimbRespMsg.Builder toSelfMsg = builderCrossTopClimbRespMsg(activityId, true);
        toSelfMsg.setSelfUserId(userId);
        toSelfMsg.setSelfAbility(ability);

        ClimbTowerProto.ClimbTowerTopClimbRespMsg.Builder toEnemyClientMsg = builderTopClimbRespMsg();
        ClimbTowerProto.CrossClimbTowerTopClimbRespMsg.Builder toEnemyMsg = builderCrossTopClimbRespMsg(activityId, false);
        long enemyServerId = 0;

        CrossUserMgr.updateUserBaseInfo(userId, userBaseInfo);

        synchronized (crossClimbTowerTop) {
            int startCell = 0;
            ClimbTowerTopData topData = crossClimbTowerTop.getTopDataByUserId(userId);
            if (null != topData) {
                startCell = topData.getCellNum();
            }

            int nextCell = startCell + 1;
            if (nextCell != targetCell) {
                return GameErrorCode.E_CLIMB_TOWER_TOP_CELL_SELF_CHANGE;
            }
            toSelfClientMsg.setOldTopCell(startCell);
            toSelfClientMsg.setNewTopCell(nextCell);

            ClimbTowerTopInfo nextTopCellConfig = CrossClimbTowerConfigMgr.getTopConfig(activityId, nextCell);
            if (null == nextTopCellConfig) {
                //爬到顶层了
                return GameErrorCode.E_CLIMB_TOWER_NOT_NEXT_TOP_CELL;
            }

            BigInteger userAbility = new BigInteger(ability);
            BigInteger enemyAbility = null;
            ClimbTowerTopData nextTopData = crossClimbTowerTop.getTopDataByCellNum(nextCell);
            if (null == nextTopData || nextTopData.getUserId() == 0) {
                //打固定怪
                if (targetUserId != 0) {
                    //目标发生变化
                    return GameErrorCode.E_CLIMB_TOWER_TOP_CELL_TARGET_CHANGE;
                }
                enemyAbility = nextTopCellConfig.getAbility();
            } else {
                //打玩家
                if (targetUserId != nextTopData.getUserId()) {
                    //目标发生变化
                    return GameErrorCode.E_CLIMB_TOWER_TOP_CELL_TARGET_CHANGE;
                }
                enemyAbility = nextTopData.getAbility();
                long enemyUserId = nextTopData.getUserId();
                UserBaseInfo enemyBaseInfo = CrossUserMgr.getUserBaseInfo(enemyUserId);
                if (null != enemyBaseInfo) {
                    nextTopData.setUserBaseInfo(enemyBaseInfo);
                }
                toSelfMsg.setEnemyBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(nextTopData.getUserBaseInfo()));
                toSelfMsg.setEnemyUserId(enemyUserId);

                toEnemyMsg.setSelfUserId(enemyUserId);
                toEnemyMsg.setSelfAbility(enemyAbility.toString());
                toEnemyMsg.setEnemyUserId(userId);
                toEnemyMsg.setEnemyAbility(ability);
                toEnemyMsg.setEnemyBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                toEnemyClientMsg.setOldTopCell(nextCell);
                toEnemyClientMsg.setNewTopCell(startCell);
                enemyServerId = nextTopData.getServerId();
            }
            toSelfMsg.setEnemyAbility(enemyAbility.toString());

            if (userAbility.compareTo(enemyAbility) < 0) {
                return GameErrorCode.E_CLIMB_TOWER_TOP_CELL_ABILITY_FAILS;
            }

            crossClimbTowerTop.winUpdateTopData(serverId, userId, userAbility, pic, lv, startCell, nextCell, userBaseInfo);

            if (nextCell > maxCell) {
                toSelfClientMsg.setReward(nextTopCellConfig.getReward());
                toSelfClientMsg.setMaxTopCell(nextCell);
            }
        }

        toSelfMsg.setRetClient(toSelfClientMsg);
        toEnemyMsg.setRetClient(toEnemyClientMsg);

        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.S_CLIMB_TOWER_TOP_CLIMB_CROSS_RESP, toSelfMsg));
        if (enemyServerId > 0 && toEnemyMsg.getSelfUserId() > 0) {
            MessageHelper.sendPacket(enemyServerId, toEnemyMsg.getSelfUserId(), YanQuMessageUtils.buildMessage(Protocol.S_CLIMB_TOWER_TOP_CLIMB_CROSS_RESP, toEnemyMsg));
        }

        return 0;
    }

    public static void updateTopCellAbility(int activityId, long serverId, long userId, String ability, int topCellNum) {
        CrossClimbTowerTop crossClimbTowerTop = getCrossClimbTowerTop(activityId);
        if (null == crossClimbTowerTop) {
            return;
        }
        int newTopCellNum = topCellNum;

        synchronized (crossClimbTowerTop) {
            ClimbTowerTopData climbTowerTopData = crossClimbTowerTop.getTopDataByUserId(userId);
            if (null != climbTowerTopData) {
                climbTowerTopData.setAbility(new BigInteger(ability));
                if (climbTowerTopData.getCellNum() != topCellNum) {
                    newTopCellNum = climbTowerTopData.getCellNum();
                }
            } else {
                newTopCellNum = 0;
            }
        }

        if (newTopCellNum != topCellNum) {
            MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(Protocol.S_CLIMB_TOWER_TOP_CELL_CHANGE_CROSS_RESP,
                    ClimbTowerProto.ClimbTowerCrossUpdateTopCellRespMsg.newBuilder().setActivityId(activityId).setTopCellNum(newTopCellNum)));
        }
    }

    public static CrossClimbTowerTop getCrossClimbTowerTop(int activityId) {
        CrossClimbTowerTop crossClimbTowerTop = activityTopMap.get(activityId);
        if (null == crossClimbTowerTop) {
            synchronized (activityTopMap) {
                crossClimbTowerTop = activityTopMap.get(activityId);
                if (null == crossClimbTowerTop) {
                    ActivityInfo activityInfo = ActivityBussiness.getActivityInfoByActivityId(activityId);
                    if (null == activityInfo) {
                        return null;
                    }
                    crossClimbTowerTop = new CrossClimbTowerTop(activityId, activityInfo.getEndShowTime());
                    activityTopMap.put(activityId, crossClimbTowerTop);
                    CrossClimbTowerConfigMgr.reloadConfig(activityId);
                }
            }
        }

        return crossClimbTowerTop;
    }

    public static void updateActivityEndTime(int activityId, long endTime) {
        CrossClimbTowerTop crossClimbTowerTop = activityTopMap.get(activityId);
        if (null == crossClimbTowerTop) {
            synchronized (activityTopMap) {
                crossClimbTowerTop = activityTopMap.get(activityId);
                if (null == crossClimbTowerTop) {
                    crossClimbTowerTop = new CrossClimbTowerTop(activityId, endTime);
                    activityTopMap.put(activityId, crossClimbTowerTop);
                    CrossClimbTowerConfigMgr.reloadConfig(activityId);
                }
            }
        } else {
            crossClimbTowerTop.setEndShowTime(endTime);
        }
    }

    public static ClimbTowerProto.ClimbTowerTopClimbRespMsg.Builder builderTopClimbRespMsg() {
        ClimbTowerProto.ClimbTowerTopClimbRespMsg.Builder builder = ClimbTowerProto.ClimbTowerTopClimbRespMsg.newBuilder();
        builder.setRet(0);
        builder.setOldTopCell(0);
        builder.setNewTopCell(0);
        builder.setMaxTopCell(0);
        builder.setReward("");

        return builder;
    }

    public static ClimbTowerProto.CrossClimbTowerTopClimbRespMsg.Builder builderCrossTopClimbRespMsg(int activityId, boolean isAttack) {
        ClimbTowerProto.CrossClimbTowerTopClimbRespMsg.Builder builder = ClimbTowerProto.CrossClimbTowerTopClimbRespMsg.newBuilder();
        builder.setIsAttack(isAttack);
        builder.setActivityId(activityId);
        builder.setSelfUserId(0);
        builder.setSelfAbility("0");
        builder.setEnemyUserId(0);
        builder.setEnemyAbility("0");

        return builder;
    }
}
